﻿using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using XinLife.Core.Helper;

namespace XinLife.Common.Setup
{
    public static class SwaggerSetup
    {
        /// <summary>
        /// swagger文档
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddSwaggerSetup(this IServiceCollection services)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            var basePath = AppContext.BaseDirectory;

            var ApiName = Appsettings.app(new string[] { "Startup", "ApiName" });
            services.AddSwaggerGen(c =>
            {
                new string[] { "XinLife" }.ToList().ForEach(version =>
                {
                    c.SwaggerDoc(version, new OpenApiInfo
                    {
                        Version = version,
                        Title = $"{ApiName} 接口文档",
                        Description = $"{ApiName} HTTP API "
                    });
                    c.AddServer(new OpenApiServer()
                    {
                        Url = "",
                        Description = "vvv"
                    });
                    c.CustomOperationIds(apiDesc =>
                    {
                        var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
                        return controllerAction?.ControllerName + "-" + controllerAction?.ActionName;
                    });
                });
                //版本控制
                //c.DocInclusionPredicate((docName, apiDesc) =>
                //{
                //    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
                //    // 检查方法和控制器上的 ApiExplorerSettingsAttribute 特性中的 GroupName
                //    var methodVersions = methodInfo.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(attr => attr.GroupName);
                //    var controllerVersions = methodInfo.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(attr => attr.GroupName);

                //    if (methodVersions.Any())
                //    {
                //        return methodVersions.Any(attr => attr == docName);
                //    }
                //    else
                //    {
                //        return controllerVersions.Any(attr => attr == docName);
                //    }
                //});
                c.CustomSchemaIds(t=>t.FullName);

                // 按相对路径排序，作者：Alby
                //c.OrderActionsBy(o => o.RelativePath);

                var xmlPath = Path.Combine(basePath, nameof(XinLife) + ".xml");//这个就是刚刚配置的xml文件名

                Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.xml").ToList().ForEach(file =>
                {
                    c.IncludeXmlComments(file, true);//默认的第二个参数是false，这个是controller的注释，记得修改
                });
                var xmlModelPath = Path.Combine(basePath, "XinLife.Model.xml");//这个就是Model层的xml文件名
                c.IncludeXmlComments(xmlModelPath);

                //c.OperationFilter<AddRequiredHeaderParameter>();
                // 开启加权小锁
                c.OperationFilter<AddResponseHeadersFilter>();
                c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();

                // 在header中添加token，传递到后台
                c.OperationFilter<SecurityRequirementsOperationFilter>();

                // Jwt Bearer 认证，必须是 oauth2
                c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格）\"",
                    Name = "Authorization",//jwt默认的参数名称
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });

                //添加安全请求
                c.AddSecurityRequirement(
                    new OpenApiSecurityRequirement {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference=new OpenApiReference{
                                    Type=ReferenceType.SecurityScheme,
                                    Id= "Bearer"
                                }
                            }
                            ,new string[] { }
                        }
                    });
            });
        }
    }
}
